#include "linux/device.h"
#include "linux/errno.h"
#include "linux/list.h"
#include "linux/kernel.h"
#include "linux/printk.h"
#include "linux/string.h"


int driver_for_each()
{
    return 0;
}

int driver_register(struct device_driver *drv)
{
	int ret = 0;
    struct device *dev;
    struct list_head *dev_list;
    struct bus_type *this_bus_head;

    if (!drv || !drv->bus || !drv->bus->match)
        return -EINVAL;

    this_bus_head = bus_find_bus_head(drv->bus);
    if (!this_bus_head)
        printk("Unregistered BUS Type: %s\n", drv->bus->name);

    if (!drv->bus->probe && !drv->probe)
        return -EINVAL;

    list_for_each(dev_list, &this_bus_head->dev_head)
    {
        dev = list_entry(dev_list, struct device, list);
        if (drv->bus->match(dev, drv))
        {
            dev->driver = drv;
            if(drv->bus->probe)
               ret = drv->bus->probe(dev);
            else if (drv->probe)
               ret = drv->probe(dev);
			else
				return -EINVAL;
			
			if (ret < 0)
				return ret;
        }
    }

    list_add_tail(&drv->list, &this_bus_head->drv_head);

    return ret;
}

void release_drv_struct(struct device_driver *drv)
{
    if (!drv)
        return;

    memset(drv, 0, sizeof(struct device_driver));
    //free(drv);
}

int driver_unregister(struct device_driver *drv)
{
    struct device *dev;
    struct list_head *dev_list;
    struct bus_type *this_bus_head;

    if (!drv)
        return -EINVAL;

    this_bus_head = bus_find_bus_head(drv->bus);
    if (this_bus_head)
    {
        list_for_each(dev_list, &this_bus_head->dev_head)
        {
            dev = list_entry(dev_list, struct device, list);
            if (drv->bus->match(dev, drv))
            {
                if(drv->bus->remove)
                    drv->bus->remove(dev);
                else if (drv->remove)
                    drv->remove(dev);
                dev->driver = NULL;
            }
        }
    }

    list_del(&drv->list);
    INIT_LIST_HEAD(&drv->list);
    //release_drv_struct(drv);
    return 0;
}

